#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <ctype.h>
#include "wrap.h"
int main(int argc, char const *argv[])
{
        if(argc < 2){
                printf("eg: ./a.out port\n");
                exit(1);       
        }
        int port = atoi(argv[1]);

        int lfd = Socket(AF_INET, SOCK_STREAM,0);

        struct sockaddr_in serv_addr;
        socklen_t serv_len = sizeof(serv_addr);
        memset(&serv_addr,0,serv_len);
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_addr.sin_port = htons(port);
        Bind(lfd,(struct sockaddr *)&serv_addr, serv_len);

        Listen(lfd,36);
        printf("Start accept ......\n");

        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);

        struct pollfd allfd[1024];
        int max_index = 0;
        for (int i = 0; i < 1024; i++){
                allfd[i].fd = -1;
        }
        allfd[0].fd = lfd;
        allfd[0].events = POLLIN;
        
        while (1){
                //委托内核做IO检测
                int ret = poll(allfd,max_index+1,-1);
                if(ret == -1){
                        perr_exit("poll error");
                }
                //判断是否有连接请求
                if(allfd[0].revents & POLLIN){
                        //接收连接请求 - accept不阻塞
                        int cfd = Accept(lfd,(struct sockaddr*)&client_addr, &client_len);      
                        if(cfd == -1){
                                perr_exit("accept error");
                        }
                        printAddr("new client connect", &client_addr);
                        //将cfd加入到poll数组中 - 下一次就可以检测到了
                        int i = 1;
                        for (; i < 1024; ++i){
                                if(allfd[i].fd == -1){
                                        allfd[i].fd = cfd;
                                        allfd[i].events = POLLIN;
                                        break;
                                }
                        }
                        //更新最后一个元素的下标
                        max_index = max_index < i ? i : max_index;
                }
                // 已经连接的客户端有数据到达 遍历数组allfd
                for ( int i = 1; i <= max_index; ++i){
                        int fd = allfd[i].fd;
                        if(fd == -1){
                                continue;
                        }
                        if(allfd[i].revents & POLLIN){
                                char buf[1024] = {0};
                                int len = recv(allfd[i].fd,buf,sizeof(buf),0);
                                if(len == -1){
                                        perr_exit("recv error");
                                }
                                else if(len == 0){
                                        allfd[i].fd = -1;
                                        Close(fd);
                                        printf("客户端已经主动断开连接\n");
                                }
                                else{
                                        printf("recv buf: %s\n", buf);
                                        for (int k = 0; k < len; ++k){
                                                buf[k] = toupper(buf[k]);
                                        }
                                        send(allfd[i].fd,buf,strlen(buf)+1, 0);
                                }
                        }
                }                
        }
        Close(lfd);
        return 0;
}
